/**
 * Copyright 2021 nicos AG
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @author Simon Petrac <spetrac@nicos-ag.com>
 * @contributor Jörg Langkau <jlangkau@nicos-ag.com>
 * @license Apache-2.0
 */

const
    tds_md_renderer                               = exports,
    md_renderer                                   = require('./renderer.md.js'),
    util                                          = require('./util.js'),
    FIR_TOP_language_literals                     = {
        // ORDERT : ALPHA
        'acceptanceCriteria':      {'en': "Acceptance Criteria"},
        'acceptance_POSITIVE':     {'en': "Accept"},
        'acceptance_NEGATIVE':     {'en': "Reject"},
        'applicability':           {'en': "Applicability"},
        'automatedTestSuite':      {'en': "Automated Test Suite"},
        'checkListApproach':       {'en': "Check List Approach"},
        'conceptReview':           {'en': "Concept Review"},
        'criteria':                {'en': "Criteria"},
        'highAssuranceEvaluation': {'en': "High Assurance Evaluation"},
        'reference':               {'en': "Reference"},
        'specificStrategy':        {'en': "Specific Strategy"},
        'topic':                   {'en': "Topic"},
        'testCases':               {'en': "Test Cases"}
    },
    FIR_ComponentTestDesignSpecificStrategyOption = {
        'ids3cm:ComponentTestDesignSpecificStrategyOption_DOCUMENT_REVIEW':    {'en': 'document review'},
        'ids3cm:ComponentTestDesignSpecificStrategyOption_FUNCTIONAL_TESTING': {'en': 'functional testing'},
        'ids3cm:ComponentTestDesignSpecificStrategyOption_SECURITY_TESTING':   {'en': 'security testing'},
        'ids3cm:ComponentTestDesignSpecificStrategyOption_SOURCE_CODE_AUDIT':  {'en': 'source code audit'},
        'ids3cm:ComponentTestDesignSpecificStrategyOption_ONSITE_VISIT':       {'en': 'onsite visit'}
    };

tds_md_renderer['FIR_STATIC_footer'] = function (param, config) {
    return md_renderer['FIR_STATIC_footer'](param, config);
}; // FIR_STATIC_footer

tds_md_renderer['FIR_TOP_CHAPTER'] = function (param, config) {
    const
        {data, graph}             = param,
        {language, specification} = config,
        componentTDS              = graph.get(specification);
    return util.getLangStringFromLiterals(componentTDS['rdfs:label'], language);
}; // FIR_TOP_CHAPTER

tds_md_renderer['FIR_TOP_description'] = function (param, config) {
    const
        {data, graph}             = param,
        {language, specification} = config,
        componentTDS              = graph.get(specification),
        description               = util.getLangStringFromLiterals(componentTDS['dct:description'], language);
    return util.textToMarkdown(description.trim());
}; // FIR_TOP_description

tds_md_renderer['FIR_TOP_reference'] = function (param, config) {
    const
        {language, specification} = config;
    return FIR_TOP_language_literals['reference'][language];
}; // FIR_TOP_reference

tds_md_renderer['FIR_TOP_criteria'] = function (param, config) {
    const
        {language, specification} = config;
    return FIR_TOP_language_literals['criteria'][language];
}; // FIR_TOP_criteria

tds_md_renderer['FIR_testDesign_criteria_content'] = function (param, config) {
    const
        {data, graph}             = param,
        {language, specification} = config,
        componentTDS              = graph.get(specification);
    if (componentTDS['ids3cm:criteria']) {
        return util.toArray(componentTDS['ids3cm:criteria'])
            .map((criteria, criteria_index, criteria_arr) => {
                const
                    criteriaId    = criteria['@id'],
                    criteriaLabel = util.getLangStringFromLiterals(criteria['rdfs:label'], language);
                return `- ${criteriaId} (${criteriaLabel})`;
            })
            .join('\n');
    } else {
        return "TODO : none?";
    }
}; // FIR_testDesign_criteria_content

tds_md_renderer['FIR_TOP_applicability'] = function (param, config) {
    const
        {language, specification} = config;
    return FIR_TOP_language_literals['applicability'][language];
}; // FIR_TOP_applicability

tds_md_renderer['FIR_testDesign_applicability_content'] = function (param, config) {
    const
        {data, graph}             = param,
        {language, specification} = config,
        componentTDS              = graph.get(specification),
        applicabilityContent      = util.getLangStringFromLiterals(componentTDS['ids3cm:testDesignApplicability'], language);
    return util.textToMarkdown(applicabilityContent);
}; // FIR_testDesign_applicability_content

tds_md_renderer['FIR_ComponentTestDesignSpecification_BaseSecurityProfile'] = function (param, config) {
    const
        {data, graph}                            = param,
        {language, specification, questionArray} = config,
        componentTDS                             = graph.get(specification),
        securityProfileType                      = 'ids3cm:ComponentTestDesignSpecification_BaseSecurityProfile',
        securityProfile                          = util.toArray(componentTDS['ids3cm:testDesignSecurityProfile'])
            .find((securityProfile) => (securityProfile['@type'] === securityProfileType));

    if (!securityProfile) return '';

    let
        profileContent             = '',
        testDesignSpecificStrategy = securityProfile['ids3cm:testDesignSpecificStrategy'],
        testDesignSpecificStrategy_type,
        checklistQuestion_array    = questionArray.sort(util.compareStrings).map(question => graph.get(question));

    profileContent += `## ${util.getLangStringFromLiterals(securityProfile['rdfs:label'], language)}\n\n`;
    profileContent += `### ${FIR_TOP_language_literals['acceptanceCriteria'][language]}\n\n`;

    profileContent += `#### ${FIR_TOP_language_literals['acceptance_POSITIVE'][language]}\n\n`;
    const positiveAcceptanceCriteria = util.getLangStringFromLiterals(securityProfile['ids3cm:testDesignAcceptanceCriteria_POSITIV'], language);
    profileContent += `${util.textToMarkdown(positiveAcceptanceCriteria.trim())}\n\n`;

    profileContent += `#### ${FIR_TOP_language_literals['acceptance_NEGATIVE'][language]}\n\n`;
    const negativeAcceptanceCriteria = util.getLangStringFromLiterals(securityProfile['ids3cm:testDesignAcceptanceCriteria_NEGATIV'], language);
    profileContent += `${util.textToMarkdown(negativeAcceptanceCriteria.trim())}\n\n`;

    if (testDesignSpecificStrategy) {

        profileContent += `### ${FIR_TOP_language_literals['specificStrategy'][language]}\n\n`;

        if (testDesignSpecificStrategy['dct:description']) {
            const strategyDescription = util.getLangStringFromLiterals(testDesignSpecificStrategy['dct:description'], language);
            profileContent += `${util.textToMarkdown(strategyDescription.trim())}\n\n`;
        }

        function render_criteriaQuestions(criteria) {
            let output = `| Id | Question | Choices |\n|---|---|---|`;
            for (let question of checklistQuestion_array) {
                if (util.toArray(question['ids3cm:criteria']).includes(criteria)) {
                    const
                        question_id          = question['@id'].replace('ids3c-co:', ''),
                        // question_label       = util.getLangStringFromLiterals(question['rdfs:label'], language),
                        question_description = util.getLangStringFromLiterals(question['dct:description'], language),
                        question_url         = 'https://github.com/International-Data-Spaces-Association/ids3c-co/tree/master/human_friendly/en/questionnaire#readme',
                        validChoices         = util.toArray(question['ids3cm:validChoice'])
                            .map(choice => util.getLangStringFromLiterals(choice['rdfs:label'], language)
                                || '_' + choice['@id'].replace('ids3c-co:', '') + '_'),
                        choices              = [
                            ...util.toArray(question['ids3cm:choice']),
                            ...util.toArray(question['ids3cm:invalidChoice'])
                        ].sort(util.compareNodes)
                            .map(choice => util.getLangStringFromLiterals(choice['rdfs:label'], language)
                                || '_' + choice['@id'].replace('ids3c-co:', '') + '_');

                    output += `\n| [${question_id}](${question_url}) | ${util.textToMarkdown(question_description.trim())} |`;
                    output += ' ' + [...validChoices.map(choice => `**${choice}**`), ...choices].join(' |\n|   |   |') + '  |';
                }
            }
            return output;
        } // render_criteriaQuestions

        function render_testDesignSpecificStrategy_type(type) {

            let result = '';

            const strategyTypeDescription = util.getLangStringFromLiterals(type['dct:description'], language);
            result += `${util.textToMarkdown(strategyTypeDescription.trim())}\n\n`;

            if (type['@id'].endsWith('ChecklistApproach') && componentTDS['ids3cm:criteria']) {
                result += `${render_criteriaQuestions(componentTDS['ids3cm:criteria'])}\n\n`;
            }

            if (type['ids3cm:automatedTestsuite']) {
                result += `#### ${FIR_TOP_language_literals['automatedTestSuite'][language]}\n\n`;
                result += `${util.getLangStringFromLiterals(type['ids3cm:automatedTestsuite'], language)}\n\n`;
            } // if ()

            if (type['ids3cm:testCaseSpecification']) {
                result += `#### ${FIR_TOP_language_literals['testCases'][language]}\n\n`;
                const testCases = util.toArray(type['ids3cm:testCaseSpecification'])
                    .sort(util.compareNodes);

                for (let testCase of testCases) {
                    const
                        testCaseId    = testCase['@id'].replace('ids3c-co:', ''),
                        testCaseLabel = util.getLangStringFromLiterals(testCase['rdfs:label'], language);
                    result += `- [${testCaseLabel}](../../case/specs/${testCaseId}.md)`;
                    result += '\n';
                }

                result += '\n';
            }

            if (type['ids3cm:testDesignSpecificStrategyTopic']) {
                result += `##### ${FIR_TOP_language_literals['topic'][language]}\n\n`;
                for (let testDesignSpecificStrategyTopic of util.toArray(type['ids3cm:testDesignSpecificStrategyTopic'])) {
                    const
                        strategyTopicDescription = util.getLangStringFromLiterals(testDesignSpecificStrategyTopic['dct:description'], language),
                        strategyOptionTags       = util.toArray(testDesignSpecificStrategyTopic['ids3cm:testDesignSpecificStrategyOption'])
                            .map(({'@id': strategyOptionId}) => FIR_ComponentTestDesignSpecificStrategyOption[strategyOptionId]?.[language]
                                || strategyOptionId.replace('ids3c-co:', '').replace('ids3cm:', '').replace('ComponentTestDesignSpecificStrategyOption_', ''))
                            .sort(util.compareStrings);

                    result += `- ${util.textToMarkdown(strategyTopicDescription.trim())}`;
                    if (strategyOptionTags.length > 0) result += ` _[${strategyOptionTags.join(', ')}]_`;
                    result += '\n';
                }
            } // if ()

            return result;
        } // render_testDesignSpecificStrategy_type()

        testDesignSpecificStrategy_type = testDesignSpecificStrategy['ids3cm:testDesignSpecificStrategy_ChecklistApproach'];
        if (testDesignSpecificStrategy_type) {
            profileContent += `#### ${FIR_TOP_language_literals['checkListApproach'][language]}\n\n`;
            profileContent += `${render_testDesignSpecificStrategy_type(testDesignSpecificStrategy_type)}\n\n`;
        } // if ()

        testDesignSpecificStrategy_type = testDesignSpecificStrategy['ids3cm:testDesignSpecificStrategy_ConceptReview'];
        if (testDesignSpecificStrategy_type) {
            profileContent += `#### ${FIR_TOP_language_literals['conceptReview'][language]}\n\n`;
            profileContent += `${render_testDesignSpecificStrategy_type(testDesignSpecificStrategy_type)}\n\n`;
        } // if ()

        testDesignSpecificStrategy_type = testDesignSpecificStrategy['ids3cm:testDesignSpecificStrategy_HighAssuranceEvaluation'];
        if (testDesignSpecificStrategy_type) {
            profileContent += `#### ${FIR_TOP_language_literals['highAssuranceEvaluation'][language]}\n\n`;
            profileContent += `${render_testDesignSpecificStrategy_type(testDesignSpecificStrategy_type)}\n\n`;
        } // if ()

    } // if (testDesignSpecificStrategy)

    return profileContent;
}; // FIR_ComponentTestDesignSpecification_BaseSecurityProfile

tds_md_renderer['FIR_ComponentTestDesignSpecification_TrustSecurityProfile'] = function (param, config) {
    const
        {data, graph}             = param,
        {language, specification} = config,
        componentTDS              = graph.get(specification),
        securityProfileType       = 'ids3cm:ComponentTestDesignSpecification_TrustSecurityProfile',
        securityProfile           = util.toArray(componentTDS['ids3cm:testDesignSecurityProfile'])
            .find((securityProfile) => (securityProfile['@type'] === securityProfileType));

    if (!securityProfile) return '';

    let
        profileContent             = '',
        testDesignSpecificStrategy = securityProfile['ids3cm:testDesignSpecificStrategy'],
        testDesignSpecificStrategy_type;

    profileContent += `## ${util.getLangStringFromLiterals(securityProfile['rdfs:label'], language)}\n\n`;
    profileContent += `### ${FIR_TOP_language_literals['acceptanceCriteria'][language]}\n\n`;

    profileContent += `#### ${FIR_TOP_language_literals['acceptance_POSITIVE'][language]}\n\n`;
    const positiveAcceptanceCriteria = util.getLangStringFromLiterals(securityProfile['ids3cm:testDesignAcceptanceCriteria_POSITIV'], language);
    profileContent += `${util.textToMarkdown(positiveAcceptanceCriteria.trim())}\n\n`;

    profileContent += `#### ${FIR_TOP_language_literals['acceptance_NEGATIVE'][language]}\n\n`;
    const negativeAcceptanceCriteria = util.getLangStringFromLiterals(securityProfile['ids3cm:testDesignAcceptanceCriteria_NEGATIV'], language);
    profileContent += `${util.textToMarkdown(negativeAcceptanceCriteria.trim())}\n\n`;

    if (testDesignSpecificStrategy) {

        profileContent += `### ${FIR_TOP_language_literals['specificStrategy'][language]}\n\n`;

        if (testDesignSpecificStrategy['dct:description']) {
            const strategyDescription = util.getLangStringFromLiterals(testDesignSpecificStrategy['dct:description'], language);
            profileContent += `${util.textToMarkdown(strategyDescription.trim())}\n\n`;
        }

        function render_testDesignSpecificStrategy_type(type) {

            let result = '';

            const strategyTypeDescription = util.getLangStringFromLiterals(type['dct:description'], language);
            result += `${util.textToMarkdown(strategyTypeDescription.trim())}\n\n`;

            if (type['ids3cm:automatedTestsuite']) {
                result += `#### ${FIR_TOP_language_literals['automatedTestSuite'][language]}\n\n`;
                result += `${util.getLangStringFromLiterals(type['ids3cm:automatedTestsuite'], language)}\n\n`;
            } // if ()

            if (type['ids3cm:testCaseSpecification']) {
                result += `#### ${FIR_TOP_language_literals['testCases'][language]}\n\n`;
                const testCases = util.toArray(type['ids3cm:testCaseSpecification'])
                    .sort(util.compareNodes);

                for (let testCase of testCases) {
                    const
                        testCaseId    = testCase['@id'].replace('ids3c-co:', ''),
                        testCaseLabel = util.getLangStringFromLiterals(testCase['rdfs:label'], language);
                    result += `- [${testCaseLabel}](../../case/specs/${testCaseId}.md)`;
                    result += '\n';
                }

                result += '\n';
            }

            if (type['ids3cm:testDesignSpecificStrategyTopic']) {
                result += `##### ${FIR_TOP_language_literals['topic'][language]}\n\n`;
                for (let testDesignSpecificStrategyTopic of util.toArray(type['ids3cm:testDesignSpecificStrategyTopic'])) {
                    const
                        strategyTopicDescription = util.getLangStringFromLiterals(testDesignSpecificStrategyTopic['dct:description'], language),
                        strategyOptionTags       = util.toArray(testDesignSpecificStrategyTopic['ids3cm:testDesignSpecificStrategyOption'])
                            .map(({'@id': strategyOptionId}) => FIR_ComponentTestDesignSpecificStrategyOption[strategyOptionId]?.[language]
                                || strategyOptionId.replace('ids3c-co:', '').replace('ids3cm:', '').replace('ComponentTestDesignSpecificStrategyOption_', ''))
                            .sort(util.compareStrings);

                    result += `- ${util.textToMarkdown(strategyTopicDescription.trim())}`;
                    if (strategyOptionTags.length > 0) result += ` _[${strategyOptionTags.join(', ')}]_`;
                    result += '\n';
                }
            } // if ()

            return result;
        } // render_testDesignSpecificStrategy_type()

        testDesignSpecificStrategy_type = testDesignSpecificStrategy['ids3cm:testDesignSpecificStrategy_ConceptReview'];
        if (testDesignSpecificStrategy_type) {
            profileContent += `#### ${FIR_TOP_language_literals['conceptReview'][language]}\n\n`;
            profileContent += `${render_testDesignSpecificStrategy_type(testDesignSpecificStrategy_type)}\n\n`;
        } // if ()

        testDesignSpecificStrategy_type = testDesignSpecificStrategy['ids3cm:testDesignSpecificStrategy_HighAssuranceEvaluation'];
        if (testDesignSpecificStrategy_type) {
            profileContent += `#### ${FIR_TOP_language_literals['highAssuranceEvaluation'][language]}\n\n`;
            profileContent += `${render_testDesignSpecificStrategy_type(testDesignSpecificStrategy_type)}\n\n`;
        } // if ()

    } // if (testDesignSpecificStrategy)

    return profileContent;
}; // FIR_ComponentTestDesignSpecification_TrustSecurityProfile

tds_md_renderer['FIR_ComponentTestDesignSpecification_TrustPlusSecurityProfile'] = function (param, config) {
    const
        {data, graph}             = param,
        {language, specification} = config,
        componentTDS              = graph.get(specification),
        securityProfileType       = 'ids3cm:ComponentTestDesignSpecification_TrustPlusSecurityProfile',
        securityProfile           = util.toArray(componentTDS['ids3cm:testDesignSecurityProfile'])
            .find((securityProfile) => (securityProfile['@type'] === securityProfileType));

    if (!securityProfile) return '';

    let
        profileContent             = '',
        testDesignSpecificStrategy = securityProfile['ids3cm:testDesignSpecificStrategy'],
        testDesignSpecificStrategy_type;

    profileContent += `## ${util.getLangStringFromLiterals(securityProfile['rdfs:label'], language)}\n\n`;
    profileContent += `### ${FIR_TOP_language_literals['acceptanceCriteria'][language]}\n\n`;

    profileContent += `#### ${FIR_TOP_language_literals['acceptance_POSITIVE'][language]}\n\n`;
    const positiveAcceptanceCriteria = util.getLangStringFromLiterals(securityProfile['ids3cm:testDesignAcceptanceCriteria_POSITIV'], language);
    profileContent += `${util.textToMarkdown(positiveAcceptanceCriteria.trim())}\n\n`;

    profileContent += `#### ${FIR_TOP_language_literals['acceptance_NEGATIVE'][language]}\n\n`;
    const negativeAcceptanceCriteria = util.getLangStringFromLiterals(securityProfile['ids3cm:testDesignAcceptanceCriteria_NEGATIV'], language);
    profileContent += `${util.textToMarkdown(negativeAcceptanceCriteria.trim())}\n\n`;

    if (testDesignSpecificStrategy) {

        profileContent += `### ${FIR_TOP_language_literals['specificStrategy'][language]}\n\n`;

        if (testDesignSpecificStrategy['dct:description']) {
            const strategyDescription = util.getLangStringFromLiterals(testDesignSpecificStrategy['dct:description'], language);
            profileContent += `${util.textToMarkdown(strategyDescription.trim())}\n\n`;
        }

        function render_testDesignSpecificStrategy_type(type) {

            let result = '';

            const strategyTypeDescription = util.getLangStringFromLiterals(type['dct:description'], language);
            result += `${util.textToMarkdown(strategyTypeDescription.trim())}\n\n`;

            if (type['ids3cm:automatedTestsuite']) {
                result += `#### ${FIR_TOP_language_literals['automatedTestSuite'][language]}\n\n`;
                result += `${util.getLangStringFromLiterals(type['ids3cm:automatedTestsuite'], language)}\n\n`;
            } // if ()

            if (type['ids3cm:testCaseSpecification']) {
                result += `#### ${FIR_TOP_language_literals['testCases'][language]}\n\n`;
                const testCases = util.toArray(type['ids3cm:testCaseSpecification'])
                    .sort(util.compareNodes);

                for (let testCase of testCases) {
                    const
                        testCaseId    = testCase['@id'].replace('ids3c-co:', ''),
                        testCaseLabel = util.getLangStringFromLiterals(testCase['rdfs:label'], language);
                    result += `- [${testCaseLabel}](../../case/specs/${testCaseId}.md)`;
                    result += '\n';
                }

                result += '\n';
            }

            if (type['ids3cm:testDesignSpecificStrategyTopic']) {
                result += `##### ${FIR_TOP_language_literals['topic'][language]}\n\n`;
                for (let testDesignSpecificStrategyTopic of util.toArray(type['ids3cm:testDesignSpecificStrategyTopic'])) {
                    const
                        strategyTopicDescription = util.getLangStringFromLiterals(testDesignSpecificStrategyTopic['dct:description'], language),
                        strategyOptionTags       = util.toArray(testDesignSpecificStrategyTopic['ids3cm:testDesignSpecificStrategyOption'])
                            .map(({'@id': strategyOptionId}) => FIR_ComponentTestDesignSpecificStrategyOption[strategyOptionId]?.[language]
                                || strategyOptionId.replace('ids3c-co:', '').replace('ids3cm:', '').replace('ComponentTestDesignSpecificStrategyOption_', ''))
                            .sort(util.compareStrings);

                    result += `- ${util.textToMarkdown(strategyTopicDescription.trim())}`;
                    if (strategyOptionTags.length > 0) result += ` _[${strategyOptionTags.join(', ')}]_`;
                    result += '\n';
                }
            } // if ()

            return result;
        } // render_testDesignSpecificStrategy_type()

        testDesignSpecificStrategy_type = testDesignSpecificStrategy['ids3cm:testDesignSpecificStrategy_ConceptReview'];
        if (testDesignSpecificStrategy_type) {
            profileContent += `#### ${FIR_TOP_language_literals['conceptReview'][language]}\n\n`;
            profileContent += `${render_testDesignSpecificStrategy_type(testDesignSpecificStrategy_type)}\n\n`;
        } // if ()

        testDesignSpecificStrategy_type = testDesignSpecificStrategy['ids3cm:testDesignSpecificStrategy_HighAssuranceEvaluation'];
        if (testDesignSpecificStrategy_type) {
            profileContent += `#### ${FIR_TOP_language_literals['highAssuranceEvaluation'][language]}\n\n`;
            profileContent += `${render_testDesignSpecificStrategy_type(testDesignSpecificStrategy_type)}\n\n`;
        } // if ()

    } // if (testDesignSpecificStrategy)

    return profileContent;
}; // FIR_ComponentTestDesignSpecification_TrustPlusSecurityProfile
